package com.andnnl.mongo;

import com.mongodb.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public abstract class MongoDAO<T extends IdEntity>
{
	// https://oss.sonatype.org/content/repositories/releases/org/mongodb/mongo-java-driver/3.2.2/
	private String tableName;
	private String dbName;

	protected abstract Class<T> getEntityClass();

	public void setTableName(String tableName)
	{
		this.tableName = tableName;
	}

	public void setDbName(String dbName)
	{
		this.dbName = dbName;
	}

	protected MongoCollection<T> _collection;
    protected MongoClient _client;

	private MongoDatabase createDatabase()
	{
		MongoClientOptions.Builder build = new MongoClientOptions.Builder();
		// 与数据最大连接数50
		build.connectionsPerHost(10000);
		// 如果当前所有的connection都在使用中，则每个connection上可以有50个线程排队等待
		build.threadsAllowedToBlockForConnectionMultiplier(500);
		build.connectTimeout(1 * 60 * 1000);
		build.maxWaitTime(2 * 60 * 1000);
		 MongoCredential credential = MongoCredential.createCredential(MongoConst.USERNAME, MongoConst.DB_NAME, MongoConst.PASSWORD.toCharArray());
		MongoClientOptions options = build.build();
		List<MongoCredential> lst=new ArrayList<MongoCredential>();
		lst.add(credential);
		ServerAddress addr = new ServerAddress(MongoConst.SERVER_IP, MongoConst.SERVER_PORT);
		//判断 是否使用用户名和密码登录
		if("true".equalsIgnoreCase(MongoConst.IS_CREDENTIAL)){
			_client = new MongoClient(addr,lst, options);
		}else{
			_client=new MongoClient(addr,options);
		}
		// 获取数据库test,不存在的话，会自动建立该数据库
		MongoDatabase db = _client.getDatabase(dbName);
		return db;
	}

	public void Close()
	{
		try
		{
			if (_client != null)
			{
				_client.close();
			}
		}
		catch (Exception ex)
		{
		}

	}

	public void getCollection(Codec<T> t)
	{

		MongoDatabase mdb = this.createDatabase();
		CodecRegistry codecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(t), MongoClient.getDefaultCodecRegistry());
		_collection = mdb.getCollection(tableName, getEntityClass()).withCodecRegistry(codecRegistry);

	}

	public T findById(String id)
	{

		Document doc = new Document("_id", new ObjectId(id));
		T t = _collection.find(doc).first();

		return t;
	}

	public void save(T t)
	{

		_collection.insertOne(t);

	}

	public void save(List<T> t)
	{

		_collection.insertMany(t);

	}

	public void insertAll(List<T> list)
	{
		_collection.insertMany(list);

	}

	public List<T> getPageList(BsonDocument filter,BasicDBObject sort,int pageNum,int pageSize)
	{
		List<T> lst=new ArrayList<T>();
		int skipn=(pageNum-1)*pageSize<=0?1:(pageNum-1)*pageSize;
		FindIterable<T> fi=_collection.find(filter).sort(sort).skip(skipn).limit(pageSize);
		 MongoCursor<T> cursor=fi.iterator();
		 while(cursor.hasNext())
		 {
			T t= cursor.next();
			lst.add(t);
		 }
		 cursor.close();

		return lst;
	}

	public List<T> getPageListOrderById(Document filter,ObjectId last_id,int pageSize)
	{
		 List<T> lst=new ArrayList<T>();
		 Document sort=Document.parse("{_id:1}");
		 if(last_id!=null)
		 {
		    filter.append("_id>", last_id);
		 }

		 FindIterable<T> fi=_collection.find(filter).sort(sort).limit(pageSize);
		 MongoCursor<T> cursor=fi.iterator();
		 while(cursor.hasNext())
		 {
			T t= cursor.next();
			lst.add(t);
		 }
		 cursor.close();
		return lst;
	}

	public boolean update(Bson arg0, Bson arg1)
	{

		UpdateOptions uo=new UpdateOptions();
		UpdateResult result=_collection.updateMany(arg0, arg1);
		return result.getModifiedCount()>0?true:false;
	}

	public boolean delete(Bson arg0)
	{
		UpdateOptions uo=new UpdateOptions();
		DeleteResult result=_collection.deleteMany(arg0);
		return result.getDeletedCount()>0?true:false;
	}
	   public void likeQuery()
	   {
	        Pattern john = Pattern.compile("joh?n");
	        BasicDBObject query = new BasicDBObject("name", john);
	        _collection.find(query);


	    }



}// end
